"""
@author: 江同学呀
@file: search_fields.py
@date: 2025/1/24 20:04
@desc:
    从搜索中检索所选字段
    https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-fields.html#search-fields-param
"""
from typing import Union, Dict, Iterable, List

from espc.orm.model.base.base import _Base
from espc.orm.model.mapping.field.base_field.base_field import _BaseField
from espc.orm.model.scripting.script import Script


class Fields(_Base):
    """
    https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-fields.html#search-fields-param
    """
    def __init__(self, field: Union[str, _BaseField], format_: str = None, include_unmapped: bool = None):
        super().__init__()
        self._fields: Union[str, _BaseField] = field
        self._format: str = format_
        self._include_unmapped: bool = include_unmapped
        return

    def _build(self) -> Union[str, Dict]:
        if not self._format and not self._include_unmapped:
            return self._fields if isinstance(self._fields, str) else self._fields._field_name
        _body: Dict = {
            "field": self._fields if isinstance(self._fields, str) else self._fields._field_name,
        }
        if self._format:
            _body["format"] = self._format
        if self._include_unmapped is not None:
            _body["include_unmapped"] = self._include_unmapped
        return _body


class Source(_Base):
    """
    https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-fields.html#source-filtering
    """

    def __init__(
            self, fields: Union[str, _BaseField, Iterable[Union[str, _BaseField]]] = None,
            includes: Iterable[Union[str, _BaseField]] = None,
            excludes: Iterable[Union[str, _BaseField]] = None
    ):
        super().__init__()
        self._fields: Union[str, _BaseField, Iterable[Union[str, _BaseField]]] = fields
        self._includes: Iterable[Union[str, _BaseField]] = includes
        self._exclude: Iterable[Union[str, _BaseField]] = excludes
        return

    def _build(self) -> Union[str, Dict, List]:
        if self._fields:
            return (
                self._fields if isinstance(self._fields, str) else (
                    self._fields._field_name if isinstance(self._fields, _BaseField) else [
                        field if isinstance(field, str) else field._field_name
                        for field in self._fields
                    ]
                )
            )

        _body: Dict = {}
        if self._includes:
            _body["includes"] = [field if isinstance(field, str) else field._field_name for field in self._includes]
        if self._exclude:
            _body["excludes"] = [field if isinstance(field, str) else field._field_name for field in self._exclude]
        return _body


class ScriptFields(_Base):
    """
    https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-fields.html#script-fields
    """
    def __init__(self, **script: Union[Script, Dict]):
        super().__init__()
        self._script: Dict[str, Union[Script, Dict]] = script
        return

    def _build(self) -> Dict:
        return {
            field: script._build() if isinstance(script, Script) else script
            for field, script in self._script.items()
        }

